home *** CD-ROM | disk | FTP | other *** search
- #ifndef lint
- static char rcsid[] = "$Header: connect.c,v 1.5 87/05/19 17:24:26 schoch Exp $";
- #endif
-
- #include "externs.h"
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/param.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <pwd.h>
- #include <errno.h>
-
- extern int errno;
-
- int sock; /* in main */
- FILE *inp, *out;
-
- connectport (opponent, port)
- char *opponent;
- u_short port;
- {
- struct sockaddr_in addr;
- struct hostent *host;
- struct passwd *mypasswd, *getpwuid();
- char *hishostname, *myname, *index(), *getpw(), *malloc();
- char myhostname[MAXHOSTNAMELEN+1];
- char *hisaddr, *myaddr;
- int hislen, mylen;
- u_long iaddr;
- uid_t getuid();
- u_short hashport(), hashaddr();
- char *copyhost();
- int s, i;
-
- if (gethostname (myhostname, MAXHOSTNAMELEN) < 0)
- error ("gethostname in connectport");
- host = gethostbyname(myhostname);
- if (host == NULL) {
- errno = 0;
- error("don't know my own name.");
- }
- mylen = host->h_length;
- myaddr = copyhost(host);
- if (hishostname = index (opponent, '@')) {
- *hishostname++ = '\0'; /* separate user and host */
- if (hishostname[0] >= '0' && hishostname[0] <= '9') {
- iaddr = inet_addr(hishostname);
- hisaddr = (char *)&iaddr;
- hislen = sizeof iaddr;
- } else {
- host = gethostbyname(hishostname);
- if (host == NULL) {
- errno = 0;
- error("Unknown host");
- }
- hislen = host->h_length;
- hisaddr = copyhost(host);
- hishostname = host->h_name;
- }
- } else {
- hislen = mylen;
- hisaddr = myaddr;
- hishostname = myhostname;
- }
- mypasswd = getpwuid ((int) getuid());
- myname = mypasswd -> pw_name;
- if (iamserver == UNSET)
- if (i = strcmp (myname, opponent))
- iamserver = (i < 0);
- else if (i = comparehost(myaddr, hisaddr, mylen))
- iamserver = (i < 0);
- if ((sock = socket (AF_INET, SOCK_STREAM, 0)) < 0)
- error ("socket in connectport");
- bzero ((char *) &addr, sizeof (addr));
- if (port != 0) {
- if (port > 1000) {
- errno = 0;
- error ("bad port number");
- }
- } else if (iamserver) {
- port = hashaddr(myaddr, port, mylen);
- port = hashaddr(hisaddr, port, hislen);
- port = hashport(myname, port);
- port = hashport(opponent, port);
- } else {
- port = hashaddr(hisaddr, port, hislen);
- port = hashaddr(myaddr, port, mylen);
- port = hashport(opponent, port);
- port = hashport(myname, port);
- }
- port += 3000;
- addr.sin_family = AF_INET;
- addr.sin_port = htons (port);
- if (iamserver) {
- s = sock;
- if (bind (s, /*(char *)*/ &addr, sizeof (addr)) < 0)
- if (errno == EADDRINUSE && iamserver == UNSET) {
- /* hope other player is server */
- iamserver = FALSE;
- close (s);
- if ((sock = socket (AF_INET, SOCK_STREAM, 0))
- < 0)
- error ("socket in connectport");
- } else
- error ("bind in connectport");
- if (iamserver) {
- if (listen (s, 1) < 0)
- error ("listen in connectport");
- while ((sock = accept (s, (struct sockaddr_in *) NULL,
- (int *) NULL)) < 0)
- if (errno != EINTR)
- error ("accept in connectport");
- close(s);
- }
- }
- if (!iamserver) {
- bcopy (hisaddr, (char *) &addr.sin_addr, hislen);
- while (connect (sock, /*(char *)*/ &addr, sizeof (addr)) < 0)
- if ( errno == EINTR || errno == ECONNREFUSED) {
- close (sock);
- sleep(2);
- if ((sock = socket (AF_INET, SOCK_STREAM, 0))
- < 0)
- error ("socket in connectport");
- } else
- error ("connect in connectport");
- }
- if ((s = dup(sock)) < 0)
- error("dup");
- if ((inp = fdopen(sock, "r")) == NULL)
- error("fdopen");
- if ((out = fdopen(s, "w")) == NULL)
- error("fdopen");
- setlinebuf(out);
- }
-
- u_short
- hashport (s, port)
- char *s;
- u_short port;
- {
- while (*s)
- port = (port << 1) + *s++;
- return (port & 0x7fff);
- }
-
- /*
- * addr is in network byte order.
- */
- u_short
- hashaddr(addr, port, len)
- u_short port;
- char *addr;
- {
-
- while (len--)
- port = (port << 1) + *addr++;
- return (port & 0x7fff);
- }
-
- char *
- copyhost(host)
- struct hostent *host;
- {
- char *ret;
-
- ret = malloc(host->h_length);
- if (ret == NULL)
- error("malloc");
- bcopy(host->h_addr, ret, host->h_length);
-
- return ret;
- }
-
- /* Compare h1 and h2 (in network byte order). The network number is
- * more significant than the host number, thus we need to call ntohl().
- */
- comparehost(h1, h2, len)
- char *h1, *h2;
- {
- auto unsigned long l1, l2;
-
- bcopy(h1, &l1, sizeof l1);
- bcopy(h2, &l2, sizeof l2);
- l1 = ntohl(l1);
- l2 = ntohl(l2);
-
- if (l1 < l2)
- return -1;
- else if (l1 > l2)
- return 1;
- return 0;
- }
-